package com.xiaoyu.base.utils.extensions

import `in`.srain.cube.request.JsonData
import android.os.Bundle
import com.xiaoyu.base.utils.ListUtil
import io.reactivex.functions.BiFunction
import io.reactivex.functions.Function
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.util.*

@Throws(JSONException::class)
fun JSONObject.toMap(): Map<String, Any?> {
    val map: MutableMap<String, Any?> = HashMap()
    val keys: Iterator<*> = this.keys()
    while (keys.hasNext()) {
        val key = keys.next() as String
        map[key] = this[key].fromJson()
    }
    return map
}

@Throws(JSONException::class, ClassCastException::class)
fun <T> JsonData.toMap(): Map<String, T> {
    val map: MutableMap<String, T> = HashMap()
    val iterator: Iterator<*> = this.keys()
    while (iterator.hasNext()) {
        val key = iterator.next() as String
        map[key] = this.get(key).fromJson() as T
    }
    return map
}

fun JsonData.toBooleanBundle(): Bundle {
    val params = Bundle()
    val keys: Iterator<*> = this.keys()
    try {
        while (keys.hasNext()) {
            val key = keys.next() as String
            ((this.get(key).fromJson()) as? Boolean)?.let {
                params.putBoolean(key, it)
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return params
}

@Throws(JSONException::class)
fun JSONArray.toList(): List<*> {
    val list: MutableList<Any?> = ArrayList()
    for (i in 0 until this.length()) {
        list.add(this[i].fromJson())
    }
    return list
}

@Throws(JSONException::class)
private fun Any.fromJson(): Any? {
    return when (this) {
        JSONObject.NULL -> null
        is JSONObject -> this.toMap()
        is JSONArray -> this.toList()
        else -> this
    }
}

fun <T> JsonData.convertRawList(mapper: Function<JsonData?, T>?): List<T> {
    return ListUtil.convertToList(this.toList(), mapper)
}

fun <E, T> JsonData.convertAsList(mapper: Function<E, T>?): List<T> {
    return ListUtil.convertToList(this.asList(), mapper)
}

fun <E, T> JsonData.convertAsListWithIndex(mapper: BiFunction<E, Int?, T>?): List<T> {
    return ListUtil.convertToListWithIndex(this.asList(), mapper)
}

fun <T> JsonData.convertRawListWithIndex(mapper: BiFunction<JsonData?, Int?, T>?): List<T> {
    return ListUtil.convertListWithIndex(this.toList(), mapper)
}
